package arena;

import java.awt.Color;
import java.io.IOException;
import java.net.URL;
import java.util.Vector;
import radar.Radar;
import logic.Coords2D;
import audio.SFX;
import audio.Soundtrack;
import com.jme.input.ChaseCamera;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.scene.Node;
import com.jme.scene.Skybox;
import com.jme.scene.Text;
import com.jme.scene.Spatial.CullHint;
import com.jme.scene.Spatial.TextureCombineMode;
import com.jme.scene.shape.Box;
import com.jme.scene.state.CullState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.RenderState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.Timer;
import com.jmex.game.state.GameState;
import editor.Grid;
import editor.Menu.OGGETTI;
import gameObjects.Bike;
import gameObjects.BikeCOM;
import gameObjects.BuildArena;
import gameObjects.BuildBonus;
import gameObjects.BuildWalls;
import gameObjects.Completed;
import gameObjects.GameOver;
import gameObjects.Hud;
import gameObjects.Key;
import gameObjects.Loading;
import gameObjects.Pause;
import gameObjects.Pill;
import gameObjects.RandomQuad;
import gameObjects.ReverseCount;
import gameObjects.RotateKeys;
import gameObjects.RotatePills;
import gameObjects.Ruby;
import gameObjects.Sky;
import gameObjects.TextureMapping;
import gameObjects.Vector3fCoords;
import gameObjects.Water;
import gameObjects.Win;
import gameObjects.Bike.POINTTO;

public class ArenaGS extends GameState{
	public enum  CAMDISTANCE{FIRST,CLOSE,MIDDLE,FAR,OFF};
	public enum  GAMESTATE{WAIT,STARTING,PAUSED,OVER,GATE,COMPLETE,NEXTLEVEL,QUIT,PLAY,WIN};
	public static Node			bonus;
	private Vector<Pill>  		pillColl;
    private Vector<Ruby>		rubyColl;
    private Vector<Key>   		keyColl;
    private Vector<BikeCOM>		bikes;
    private Vector3fCoords 		walls3D;
    private GAMESTATE			currentState = GAMESTATE.STARTING;
	private boolean				isDebugMode;
	private boolean				isMusicPlaying;
	private boolean				isPaused;
	private int 				startTime = 0;
	private int					countDown = 3;
	private int					endTime = 0;
	private int					speed = 25;
	private int 				currCount;
	private int					coins = 0;
	private int					keys = 15;
	private int					pillTime = 15;
	private int					levels=0;
    private int 				players=6;
    private int					humanColor;
	private DisplaySystem 		display;  
	private Renderer 			renderer; 
	private Hud					hud;		
	private Node 				rootNode  =	null;
	private Node 				occluders = null;
	private Node				scene     =	null;
	private Node 				skyNode;
	private Node				waterNode;
	private StringBuffer 		updateBuffer = new StringBuffer(30);
	private Timer 				timer;
	private Cam					cam;
	private static Camera 		camera;
	private ChaseCamera   		chaser;
    private Node 				fpsNode;
    private Text 				fps;
    private LightState      	lightState;
    private TextureMapping   	tsMap;
    private Bike 		   		human;
    //private FighterPlayer  		human;
    private ReverseCount		counter;
    private GameOver			gameover;
    private Pause				pause;
    private CAMDISTANCE			camDistance;
    private String 				fontLocation = Text.DEFAULT_FONT;
    private Soundtrack 			music;
    private Skybox 				skyBox;
    private Box 				waterBox;
    private Loading 			loading;
    private Water				gate;
    private Node	 			wallNode;
    private String				levelLoaded;
    private RotatePills 		rotP;
    private RotateKeys			rotK;
    private Arena				arena;
    private ArenaRPS			rps;
    private static ArenaGS		arenaGS;
    
    public static ArenaGS getInstance()
    {
    	if(arenaGS==null)
    		arenaGS=new ArenaGS();
    	return arenaGS;
    }
    
    public ArenaGS()
    {
    	super();
    }
    
    public void setGame(String name,int color, int players,String level,Arena arena)
    {
    	setName(name);
		this.levelLoaded=level; //mappa caricata dal giocatore
		this.players=players;	//numero di giocatori
		humanColor = color;		//colore del veicolo
		this.arena=arena;
		try {
			loadGame();
		} catch (IOException e) {
			e.printStackTrace();
		}
    }
    
    private void loadGame() throws IOException
    {
    	levels++;				//prossimo livello
		isPaused=false;			//gioco in pausa
		currCount=3;			//conto alla rovescia
		isDebugMode=false;		//debug mode
		isMusicPlaying=false;		//posso suonare?
		scene = new Node();		//scena 3D
		occluders = new Node();	//oggetti che creano ombre
		String levelName;
    	new Grid();
		if (this.levelLoaded.length()>0)
			levelName = this.levelLoaded;
		else
			levelName = "level" + levels;
		URL url = Arena.class.getClassLoader().getResource("levels/" + levelName  + ".dat");
		Grid.loadGrid(url.getPath());
		url = Arena.class.getClassLoader().getResource("levels/" + levelName + ".exp");
		Grid.loadWalls(url.getPath());
		url = Arena.class.getClassLoader().getResource("textures/confTitle.png");
		
		System.out.println(Radar.getInstance().toString());
		Radar.getInstance().getPanel().getArena();
    	
		setKeyBinding();
		
		loading = new Loading();
		loading.update(0);
		initGameFirst();
		loading.update(30);
		initGameSecond();
		loading.update(70);
		initGameThird();
		loading.update(100);
		loading.cleanup();
	}
    
    /**
     * PRIMA PARTE DELL?INIZIALIZZAZIONE DEL 3D
     * @throws IOException
     */
	private void initGameFirst() throws IOException
	{	
		//scelgo uno startpoint a caso
		int e = (int) (Math.random() * Grid.startPoints.size());
		Coords2D sp = Grid.startPoints.get(e);
					  Grid.startPoints.remove(e);
		POINTTO p = null;
		if (sp.getY()>63) p = POINTTO.SOUTH;
		if (sp.getY()<64) p = POINTTO.NORTH;
        
		/******************
		 * CREO I VEICOLI *
		 ******************/
		human = new Bike("PLAYER",sp,p,humanColor,true,scene,this.speed);
		//human = new FighterPlayer("PLAYER",sp,p,humanColor,true,scene,this.speed);
		bikes = new Vector<BikeCOM>();
		for (int i=0;i<players;i++)
		{
			bikes.add(new BikeCOM("COM"+i,i,false,scene,this.speed));
		}
		
		display 	= DisplaySystem.getDisplaySystem();
		renderer 	= display.getRenderer();
		rootNode 	= new Node("rootNode");
		
		loading.update(10); //siamo al 10%
		CullState cs = display.getRenderer().createCullState();
		cs.setCullFace(CullState.Face.Back);
		scene.setRenderState(cs); //renderizzo solo la parte visibile della scena.
		
		lightState = display.getRenderer().createLightState();   
        lightState.setGlobalAmbient(new ColorRGBA(0.1f,0.1f,0.1f,0.6f));
        lightState.setEnabled(true);
        
        Light_Direction neon  = new Light_Direction(true, new Vector3f(-1, -1, 0));
        Light_Spot      sun   = new Light_Spot(false, new Vector3f(64, 40, 64));
                        sun.setAmbient(new ColorRGBA(1f,1f,1f,0.7f));
        
        lightState.detachAll();
        lightState.attach(neon);
        lightState.attach(sun); 
		
        loading.update(20);
        
        cam			= new Cam(renderer,display,(Node) human.getModel3D());
		camera 		= cam.getCamera(); camera.setLocation(new Vector3f(sp.getX(), 3f, sp.getY()));camera.update();
		chaser 		= cam.getChaser();
		camera.setLocation(new Vector3f(64,100,32));
		camDistance=CAMDISTANCE.FAR;
		renderer.setCamera(camera);
        
		rootNode.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
		rootNode.setRenderState(lightState);
        rootNode.updateGeometricState(0.0f, true );
        rootNode.updateRenderState();
	}
	
	/**
	 * SECONDA PARTE DELL'INIZIALIZZAZIONE 3D
	 * @throws IOException
	 */
	private void initGameSecond() throws IOException
	{
		System.out.println("SECOND");
		new ColorRGBA();
		new Vector3f();
			
		timer = Timer.getTimer();               
                        
		fps = Text.createDefaultTextLabel("FPS label");
        fps.setCullHint(CullHint.Never);
        fps.setTextureCombineMode(TextureCombineMode.Replace);
 
        fpsNode = new Node("FPS node");
        fpsNode.setRenderState(fps.getRenderState(RenderState.StateType.Blend));
        fpsNode.setRenderState(fps.getRenderState(RenderState.StateType.Texture));
        fpsNode.attachChild(fps);
        fpsNode.setCullHint(CullHint.Never);
        
        loading.update(50);
        
        hud = new Hud();
        
        ZBufferState buf = renderer.createZBufferState();
        buf.setEnabled(true);
        buf.setFunction(ZBufferState.TestFunction.LessThanOrEqualTo);
        rootNode.setRenderState(buf);
        
		counter = new ReverseCount();
		gameover = new GameOver();
		pause = new Pause();
		
		for(int i=0;i<bikes.size();i++)
		{
			occluders.attachChild(((BikeCOM) bikes.get(i)).getModel3D()); 
		}
		
		occluders.attachChild(human);
		occluders.attachChild(BuildArena.getInstance().create());
		
		/*************************
		 * CREO IL NODE DEL GATE *
		 *************************/
		waterBox = new Box("GATE", new Vector3f(-4, 0, -4), new Vector3f(0,20,0));
		waterBox.setCastsShadows(true);
		waterBox.setLocalTranslation(62,-21,62);
		
		waterNode = new Node("WATERNODE");
		waterNode.attachChild(waterBox);
        occluders.attachChild(waterNode);
		
	}
	
	/**
	 * TERZA PARTE DELL'INIZIALIZZAZIONE 3D
	 * @throws IOException
	 */
	private void initGameThird() throws IOException
	{
		System.out.println("THIRD");
		bonus = new Node("BONUS");
		bonus = BuildBonus.getInstance().create();
		
		pillColl = BuildBonus.getInstance().getPills();
		rubyColl = BuildBonus.getInstance().getRubies();
		keyColl = BuildBonus.getInstance().getKeys();
		
		occluders.attachChild(bonus);
		occluders.attachChild(BuildWalls.getInstance().create());
		
		scene.attachChild(RandomQuad.getInstance().create());
		 loading.update(75);
		scene.attachChild(occluders);
		 loading.update(82);
		scene.attachChild(Sky.getInstance().create());
		 loading.update(83);
        
		rootNode.attachChild(scene);
		rootNode.attachChild(hud);
		rootNode.attachChild(counter);
        /*rootNode.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
		rootNode.setRenderState(lightState);*/
		
		loading.update(85);
        
		rootNode.updateGeometricState(0.0f, true );
        rootNode.updateRenderState();
        
        loading.update(90);
        
        fpsNode.updateGeometricState(0.0f, true );
        fpsNode.updateRenderState();
        
        loading.update(99);
        /***************************
         * ROTAZIONE DEGLI OGGETTI *
         ***************************/
        rotP = new RotatePills(pillColl);
        rotK = new RotateKeys(keyColl);
        
        Radar.getInstance().getPanel().getArena(); 
        timer.reset();
	}
	
	
	public Node getOccludersNode()
	{
		return occluders;
	}
 
	public Node getRootNode()
	{
		return rootNode;
	}
 
	public Node getFpsNode()
	{
		return fpsNode;
	}
 
	public Node getSceneNode()
	{
		return scene;
	}
	
	private void clear()
	{
		lightState.detachAll();
		scene.detachAllChildren();
		occluders.detachAllChildren();
		rootNode.detachAllChildren();
		fpsNode.detachAllChildren();
		rps.rPass.clearPassStates();
		
	}
	
	public void setRps(ArenaRPS rps)
	{
		this.rps = rps;
	}
	
	
	@Override
    public void render(float tpf)
	{
        renderer.clearBuffers();
		renderer.draw(rootNode);
        renderer.draw(fpsNode);
    }
	
	/*************************************************
	 * UPDATE DEL RENDERING. QUESTA E' LA PARTE PIU' *
	 * IMPORTANTE DEL GIOCO PERCHE' QUI SI AGGIORNA  *
	 * TUTTO IL MONDO 3D!!!                          *
	 *************************************************/
    @Override
    public void update(float tpf)
    {
    	timer.update();
    	tpf = timer.getTimePerFrame();
    	
    	try {
			checkKeyBinding();
		} catch (IOException e) {
			e.printStackTrace();
		}
    	
    	switch(currentState)
    	{
    	case STARTING	:	startGame(); 	break;
    	case PAUSED		:	pauseGame(); 	break;
    	case OVER		:	endGame();	 	break;
    	case COMPLETE	:	completeGame(); break;
    	case PLAY		:	playGame(tpf);	break;
    	case QUIT		:   quitGame();		break;
    	case GATE		:	openGate();		break;
    	case WIN		:	youWin();		break;
    	}
    }
 
    @Override
    public void cleanup()
    {
    	
    	for(int i=0;i<bikes.size();i++)
    		bikes.get(i).getBike().stop();
    	human.stop();
    	
    	renderer.clearBuffers();
		renderer.clearColorBuffer();
		renderer.clearQueue();
		renderer.clearStencilBuffer();
    	lightState.detachAll();
    	
    	/*TextureManager.doTextureCleanup();
        if (DisplaySystem.getDisplaySystem() != null && renderer != null) renderer.cleanup();
        KeyInput.destroyIfInitalized();
        MouseInput.destroyIfInitalized();
        JoystickInput.destroyIfInitalized();*/
        
    	Radar.getInstance().close();
        music.Stop();
        arena.cleanup();
    }
    
    public URL getResource(String Path)
    {
    	System.out.println("Path URL: " + Path);
    	URL res = ArenaGS.class.getClassLoader().getResource(Path);
    	return res;
    }
    
    private void printDebug(float tpf)
    {
    	String point=human.getCurrentDirection().name();
        updateBuffer.setLength(0);
        
        float posX = ((human.getModel3D().getLocalTranslation().getX()*100))/100;
        float posZ = ((human.getModel3D().getLocalTranslation().getZ()*100))/100;
        point = "Frame: " + ((int) (tpf*1000)) + ", posX:" + posX + ", posZ:" + posZ + ", " + point; 
        updateBuffer.append(point);
        if (isDebugMode) fps.print( updateBuffer ); else fps.print("");
        
		fpsNode.updateGeometricState(tpf, true);
		rootNode.updateGeometricState(tpf, true);
    }
    
    private void checkCamPosition(float tpf)
    {
    	if (camDistance!=CAMDISTANCE.OFF)
    	{
    		switch(camDistance)
    		{
    		case FAR:
    		{
    			System.out.println("CAMERA FAR");
    			chaser.setLooking(true);
    			chaser.setMaintainAzimuth(false);
    			chaser.setMaxDistance(10.0f);
    			chaser.setMinDistance( 7.0f);
    			chaser.setStayBehindTarget(true);
    			chaser.setTargetOffset(new Vector3f(0.0f, 3.0f, 0.0f));
    			break;
    		}
    		case MIDDLE:
    		{
    			System.out.println("CAMERA MIDDLE");
    			chaser.setLooking(true);
    			chaser.setMaintainAzimuth(false);
    			chaser.setMaxDistance(7.0f);
    			chaser.setMinDistance(5.0f);
    			chaser.setStayBehindTarget(true);
    			chaser.setTargetOffset(new Vector3f(0.0f, 2.0f, 0.0f));
    			break;
    		}
    		case CLOSE:
    		{
    			System.out.println("CAMERA CLOSE");
    			chaser.setLooking(true);
    			chaser.setMaintainAzimuth(false);
    			chaser.setMaxDistance(3.0f);
    			chaser.setMinDistance(1.0f);
    			chaser.setStayBehindTarget(true);
    			chaser.setTargetOffset(new Vector3f(0.0f, 1.0f, 0.0f));
    			break;
    		}
    		case FIRST:
    		{
    			System.out.println("CAMERA FIRST");
    			chaser.setLooking(true);
    			chaser.setMaintainAzimuth(false);
    			chaser.setMaxDistance(0.0f);
    			chaser.setMinDistance(0.0f);
    			chaser.setStayBehindTarget(false);
    			chaser.setTargetOffset(new Vector3f(0.0f, 5.0f, 0.0f));
    			break;
    		}
    		}
    		chaser.setTarget(human.getModel3D());
    		chaser.update(tpf);
    		camDistance = CAMDISTANCE.OFF;
    	}
    }
    
    private void setKeyBinding()
    {
    	KeyBindingManager.getKeyBindingManager().set("exit",KeyInput.KEY_ESCAPE);
		KeyBindingManager.getKeyBindingManager().set("pause", KeyInput.KEY_P);
		KeyBindingManager.getKeyBindingManager().set("reset", KeyInput.KEY_R);
		KeyBindingManager.getKeyBindingManager().set("gameover", KeyInput.KEY_Q);
		KeyBindingManager.getKeyBindingManager().set("debug", KeyInput.KEY_D);
		KeyBindingManager.getKeyBindingManager().set("far", KeyInput.KEY_1);
		KeyBindingManager.getKeyBindingManager().set("middle", KeyInput.KEY_2);
		KeyBindingManager.getKeyBindingManager().set("close", KeyInput.KEY_3);
		KeyBindingManager.getKeyBindingManager().set("first", KeyInput.KEY_4);		
		KeyBindingManager.getKeyBindingManager().set("explosion", KeyInput.KEY_X);
		KeyBindingManager.getKeyBindingManager().set("music", KeyInput.KEY_M);
		KeyBindingManager.getKeyBindingManager().set("gate", KeyInput.KEY_G);
		KeyBindingManager.getKeyBindingManager().set("completed", KeyInput.KEY_RETURN);
		KeyBindingManager.getKeyBindingManager().set("moreSpeed", KeyInput.KEY_F11);
		KeyBindingManager.getKeyBindingManager().set("lessSpeed", KeyInput.KEY_F12);
		KeyBindingManager.getKeyBindingManager().set("winner", KeyInput.KEY_V);
    }
    
    private void checkKeyBinding() throws IOException
    {
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit",false))		{currentState=GAMESTATE.QUIT;return;}
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("gameover",false)) 	{currentState = GAMESTATE.OVER; return;}
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("debug",false)) 	isDebugMode=!isDebugMode;
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("far",false)) 		camDistance=CAMDISTANCE.FAR;
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("middle",false)) 	camDistance=CAMDISTANCE.MIDDLE;
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("close",false)) 	camDistance=CAMDISTANCE.CLOSE;
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("first",false)) 	camDistance=CAMDISTANCE.FIRST;
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("explosion",false))	{human.explode();}
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("music",false))		{if (music.isPlaying()) music.Stop(); else music.Play();}
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("gate",false))		{currentState = GAMESTATE.GATE;}
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("completed",false))	{if (levels==10) cleanup(); else nextLevel();}
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("reset",false))	{levels--; nextLevel();}
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("winner",false)) {currentState=GAMESTATE.COMPLETE;return;}
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("moreSpeed",false))
    	{
    		this.speed=this.speed+5;
    		for (int i=0;i<bikes.size();i++)
    			bikes.get(i).getBike().setSpeed(this.speed);
    		human.setSpeed(speed);
    	}
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("lessSpeed",false))
    	{
    		this.speed=this.speed-5;
    		if (speed<10) speed = 10;
    		for (int i=0;i<bikes.size();i++)
    			bikes.get(i).getBike().setSpeed(this.speed);
    		human.setSpeed(speed);
    	}
    	if (KeyBindingManager.getKeyBindingManager().isValidCommand("pause",false))
    	{
    		System.out.println("PAUSE");
    		if (currentState==GAMESTATE.PLAY)
    			currentState =  GAMESTATE.PAUSED;
    		else
    		{
    			currentState =  GAMESTATE.PLAY;
    			isPaused=false;
    		}
    	}
    }
    
    private void nextLevel() throws IOException
    {
    	System.out.println("ALTRO LIVELLO");
    	for(int i=0;i<bikes.size();i++)
    		bikes.get(i).getBike().kill();
    	music.Stop();
    	clear();
    	
    	if (levels<10)
    	{
	    	loadGame();
	    	startTime=0;
	    	currentState = GAMESTATE.STARTING;
    	}
    	else
    	{
    		currentState=GAMESTATE.WIN;
    	}
    }
    
    private void startGame()
    {
    	//CONTO ALLA ROVESCIA
		timer = Timer.getTimer();
		timer.update();
		
		if (startTime==0) 
			startTime = (int) timer.getTimeInSeconds();
		endTime = (int) timer.getTimeInSeconds();
		
		if(endTime-startTime==1)
		{
			System.out.println("STARTING:" + (endTime-startTime));
			startTime=endTime;
			switch(countDown)
			{
			case 3:new SFX("sound/THREE.ogg", false, 0.2f, 0.2f, true);break;
			case 2:new SFX("sound/TWO.ogg", false, 0.2f, 0.2f, true);  break;
			case 1:new SFX("sound/ONE.ogg", false, 0.2f, 0.2f, true);  break;
			case 0:
				currentState = GAMESTATE.PLAY; 
				counter.hide(); 
				Radar.getInstance().clear();
				Radar.getInstance().getPanel().drawMap();
				Radar.getInstance().getPanel().getArena(); 
				return;
			}
			counter.applyTexture(countDown);
			counter.updateRenderState();
			countDown--;
		}
    }
    
    private void endGame()
    {
    	rootNode.attachChild(gameover);
		gameover.applyTexture();
		rootNode.updateRenderState();
		chaser.setMaxDistance(200);
		chaser.setMinDistance(200);
		chaser.setTargetOffset(new Vector3f(0, 0, 0));
		rootNode.setCullHint(CullHint.Never);
		rootNode.updateRenderState();
		new SFX("sound/GAMEOVER.ogg", false, 0.2f, 0.2f, true);
		for (int i=0;i<bikes.size();i++)((BikeCOM) bikes.get(i)).sfxStop();
		human.sfxStop();
		currentState = GAMESTATE.WAIT;
    }
    
    private void playGame(float tpf)
    {
    	pause.hide();
    	if (!isMusicPlaying) 
		{
			music = new Soundtrack("sound/title01.ogg", true, 0.5f, 0.5f, true);
			music.setVolume(1.0f);
			isMusicPlaying=true;
		}
    	if (!human.isAlive) 
    	{
    		currentState = GAMESTATE.OVER;
    		return;
    	}
    	if (human.isCompleted())
    	{
    		currentState = GAMESTATE.COMPLETE;
    		return;
    	}
    	if (human.gate)
    	{
    		currentState = GAMESTATE.GATE;
    		human.gate=false;
    		return;
    	}
    	
    	/*************************
		 * MOVIMENTO DEI VEICOLI *
		 *************************/
		human.update(tpf);
		human.setCubeUpdate(tpf);
		for (int i=0;i<bikes.size();i++)
			bikes.get(i).updateMovement(tpf);
		chaser.update(tpf);
		
		/************************************
		 *  SCRIVO LE INFORMAZIONI DI DEBUG *
		 ************************************/
		printDebug(tpf);
		
		/***********************
		 * ROTAZIONE DEI BONUS *
		 ***********************/
		rotP.update(tpf);
		rotK.update(tpf);
		
		/***********************************
		 *  CONTROLLO LA VISUALE DELLA CAM *
		 ***********************************/
		checkCamPosition(tpf);
    }
    
    private void pauseGame()
    {
    	if (!isPaused)
    	{
    		rootNode.attachChild(pause);
    		rootNode.updateRenderState();
    		isPaused=true;
    	}
		
    }
    
    private void completeGame()
    {
    	System.out.println("COMPLETAMENTO LIVELLO");
		
    	if (levels==10)
    		youWin();
    	else
    	{
	    	Completed c =  new Completed();
			rootNode.attachChild(c);
			rootNode.updateRenderState();
			new SFX("sound/off6.ogg", false, 0.2f, 0.2f, true);
			currentState = GAMESTATE.WAIT;
			startTime=0;
    	}
    }
    
    private void youWin()
    {
    	System.out.println("COMPLETAMENTO LIVELLO");
		Win c =  new Win(); 
		rootNode.attachChild(c);
		rootNode.updateRenderState();
		new SFX("sound/youwin.ogg", false, 0.2f, 0.2f, true);
		currentState = GAMESTATE.WAIT;
		startTime=0;
    	System.out.println("HAI FINITO IL GIOCO!!!");
    }
    
    private void quitGame()
    {
    	cleanup();
    }
    
    private void openGate()
    {
    	new SFX("sound/off1.ogg", false, 0.2f, 0.2f, true);
		
		gate = new Water();
		gate.init(waterBox,scene);
		for (int i=0;i<4;i++)
		{
			for(int j=0;j<4;j++)
			{
				Grid.setCell(62+i, 62+j,OGGETTI.GATE);
				Radar.getInstance().getPanel().setCell(new Color(50, 100, 50), new Coords2D(62+i,62+j));
			}
		}
		currentState = GAMESTATE.PLAY;
    }
    
    public Bike getHuman()
    {
    	return human;
    }
}